from redis.asyncio import Redis
from typing import Optional

from settings.config import settings
from common.exception.errors import CustomException
from common.response.response_code import HttpCode
from common.log import log

class RedisClient(Redis):
    def __init__(self, url: Optional[str] = None):
        self._redis_url = url or settings.REDIS_URL
        self._redis_pool: Optional[Redis] = None

    async def init_redis(self):
        """初始化Redis连接池"""
        if self._redis_pool is None:
            try:
                self._redis_pool = await Redis.from_url(self._redis_url)
            except Exception as e:
                log.error(f"初始化 redis 失败: {e}")
                raise CustomException(
                    msg="初始化 redis 失败",
                    code=HttpCode.HTTP_500
                )
                
    async def delete_with_prefix(self, prefix: str, exclude: str | list = None):
        """删除指定前缀的所有 key

        Args:
            prefix (str): 前缀
            exclude (str | list, optional): 删除白名单. Defaults to None.
        """
        keys = []
        async for key in self.scan_iter(match=f'{prefix}*'):
            if isinstance(exclude, str):
                if key != exclude:
                    keys.append(key)
            elif isinstance(exclude, list):
                if key not in exclude:
                    keys.append(key)
            else:
                keys.append(key)
        if keys:
            await self.delete(*keys)

    async def close(self):
        """关闭Redis连接池"""
        if self._redis_pool:
            try:
                await self._redis_pool.close()
            except Exception as e:
                log.error(f"关闭 redis 失败: {e}")
                raise CustomException(
                    msg="关闭 redis 失败",
                    code=HttpCode.HTTP_500
                )
            self._redis_pool = None
            
redis_client = RedisClient()